﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel;
using System.Configuration;

namespace Peer
{
    public class PeerImplementation : IPeer
    {
        private string Member;
        private string BasePath;
        private FileSystemWatcher Watcher;
        private bool isLastPeer = false;
        private bool isFirstPeer = false;
        
        public event EventHandler UpdateScreen;
        public event EventHandler SyncEvent;
       
        

        public PeerImplementation(string member, string basePath, FileSystemWatcher watcher)
        {
            this.Member = member;
            this.BasePath = basePath;
            this.Watcher = watcher;
        }

        #region IPeer Members

        public void Join(string id)
        {            

            if(!this.Member.Equals(id))
                Console.WriteLine("["+ id + " Entrou]");
        }



        public void ResponseSync(string id)
        {
            if (this.Member.Equals(id))
            {
                foreach (string name in Directory.GetFiles(BasePath))
                {
                    Watcher.EnableRaisingEvents = false;
                    File.Delete(Path.Combine(BasePath, name));
                    this.UpdateScreen(this, new EventUpdateScreenArgs("Exclusão do arquivo " + Path.GetFileName(name)));
                    Watcher.EnableRaisingEvents = true;
                }
            }
        }
        public void Sync(string id)
        {
            if (!this.Member.Equals(id) && !isLastPeer)
            {
                this.SyncEvent(this, new ResponseSyncEventArgs(id));
                this.isLastPeer = true;
            }
        }

        public void Create(CreateMessage msg)
        {
            if (!msg.id.Equals(this.Member))
            {
                try
                {
                    
                    string fileName = Path.Combine(this.BasePath, msg.Metadata.FileName);
                    if (!File.Exists(fileName))
                    {
                        this.Watcher.EnableRaisingEvents = false;
                        using (FileStream outfile = new FileStream(fileName, FileMode.Create))
                        {

                            const int bufferSize = 65536; // 64K

                            Byte[] buffer = new Byte[bufferSize];
                            int bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);

                            while (bytesRead > 0)
                            {
                                outfile.Write(buffer, 0, bytesRead);
                                bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);
                            }

                        }

                        this.UpdateScreen(this, new EventUpdateScreenArgs("Criação do arquivo " + msg.Metadata.FileName));
                        Watcher.EnableRaisingEvents = true;
                    }
                    
                }
                catch (IOException e)
                {
                    throw new FaultException<IOException>(e);
                }
            }
        }

        public void Delete(DeleteMessage msg)
        {
            if (!msg.id.Equals(this.Member))
            {
                this.Watcher.EnableRaisingEvents = false;
                string fileName = Path.Combine(this.BasePath, msg.DeletedMetadata.FileName);
                File.Delete(fileName);
                this.UpdateScreen(this, new EventUpdateScreenArgs("Exclusão do arquivo " + msg.DeletedMetadata.FileName));
                this.Watcher.EnableRaisingEvents = true;

            }
        }

        public void Change(ChangeMessage msg)
        {
            if (!msg.id.Equals(this.Member))
            {
                try
                {
                    this.Watcher.EnableRaisingEvents = false;
                    string fileName = Path.Combine(this.BasePath, msg.NewMetadata.FileName);

                    using (FileStream outfile = new FileStream(fileName, FileMode.Create))
                    {

                        const int bufferSize = 65536; // 64K

                        Byte[] buffer = new Byte[bufferSize];
                        int bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);

                        while (bytesRead > 0)
                        {
                            outfile.Write(buffer, 0, bytesRead);
                            bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);
                        }                       
                    }
                    this.UpdateScreen(this, new EventUpdateScreenArgs("Alteração do arquivo " + msg.NewMetadata.FileName));
                    this.Watcher.EnableRaisingEvents = true;
                }
                catch (IOException e)
                {
                    throw new FaultException<IOException>(e);
                }
            }
        }

        public void Rename(RenameMessage msg)
        {
            if (!msg.id.Equals(this.Member))
            {
                try
                {
                    this.Watcher.EnableRaisingEvents = false;
                    string OldfileName = Path.Combine(this.BasePath, msg.OldMetadata.FileName);
                    File.Delete(OldfileName);

                    string NewfileName = Path.Combine(this.BasePath, msg.NewMetadata.FileName);
                    using (FileStream outfile = new FileStream(NewfileName, FileMode.Create))
                    {

                        const int bufferSize = 65536; // 64K

                        Byte[] buffer = new Byte[bufferSize];
                        int bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);

                        while (bytesRead > 0)
                        {
                            outfile.Write(buffer, 0, bytesRead);
                            bytesRead = msg.FileByteStream.Read(buffer, 0, bufferSize);
                        }
                        
                    }
                    this.UpdateScreen(this, new EventUpdateScreenArgs("Renomeação de " + msg.OldMetadata.FileName + " para " + msg.NewMetadata.FileName));
                    this.Watcher.EnableRaisingEvents = true;
                }
                catch (IOException e)
                {
                    throw new FaultException<IOException>(e);
                }
            }
        }        

        #endregion

    





    }
}
